package com.gitee.wsl.mathematics.algebraic.sample

import com.gitee.wsl.mathematics.algebraic.op.Norm
import com.gitee.wsl.mathematics.algebraic.op.PowerOperations
import com.gitee.wsl.mathematics.algebraic.ExtendedField
import kotlin.math.abs
import kotlin.math.pow as kpow

interface FloatExtendedField: ExtendedField<Float>, Norm<Float, Float>

/**
 * A field for [Float] without boxing. Does not produce an appropriate field element.
 */
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
 object Float32Field : FloatExtendedField {

    override val zero: Float get() = 0.0f
    override val one: Float get() = 1.0f

    override fun number(value: Number): Float = value.toFloat()

    override fun binaryOperationFunction(operation: String): (left: Float, right: Float) -> Float =
        when (operation) {
            PowerOperations.POW_OPERATION -> { l, r -> l.kpow(r) }
            else -> super.binaryOperationFunction(operation)
        }

    override fun add(left: Float, right: Float): Float = left + right
    override fun scale(a: Float, value: Double): Float = a * value.toFloat()

    override fun multiply(left: Float, right: Float): Float = left * right

    override fun divide(left: Float, right: Float): Float = left / right

    override fun sin(arg: Float): Float = kotlin.math.sin(arg)
    override fun cos(arg: Float): Float = kotlin.math.cos(arg)
    override fun tan(arg: Float): Float = kotlin.math.tan(arg)
    override fun acos(arg: Float): Float = kotlin.math.acos(arg)
    override fun asin(arg: Float): Float = kotlin.math.asin(arg)
    override fun atan(arg: Float): Float = kotlin.math.atan(arg)

    override fun sinh(arg: Float): Float = kotlin.math.sinh(arg)
    override fun cosh(arg: Float): Float = kotlin.math.cosh(arg)
    override fun tanh(arg: Float): Float = kotlin.math.tanh(arg)
    override fun asinh(arg: Float): Float = kotlin.math.asinh(arg)
    override fun acosh(arg: Float): Float = kotlin.math.acosh(arg)
    override fun atanh(arg: Float): Float = kotlin.math.atanh(arg)

    override fun sqrt(arg: Float): Float = kotlin.math.sqrt(arg)
    override fun power(arg: Float, pow: Number): Float = arg.kpow(pow.toFloat())

    override fun exp(arg: Float): Float = kotlin.math.exp(arg)
    override fun ln(arg: Float): Float = kotlin.math.ln(arg)

    override fun norm(arg: Float): Float = abs(arg)

    override fun Float.unaryMinus(): Float = -this
    override fun Float.plus(arg: Float): Float = this + arg
    override fun Float.minus(arg: Float): Float = this - arg
    override fun Float.times(arg: Float): Float = this * arg
    override fun Float.div(arg: Float): Float = this / arg
}
 typealias FloatField = Float32Field

 val Float.Companion.algebra: Float32Field get() = Float32Field